﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using System.Collections;
namespace WindowsGame4
{
    public class ParticleEmitter : GameObject
    {
        public GameObject target;
        public List<GameObject> particles;
        public bool bHoming, bAccelerate, bDieOnFade, bRandomVel;
        public float fadeRate, scaleRate, particleLifeTime;
        public float nEmits;
        public float minAngle, maxAngle, minDistance, maxDistance, minScale, maxScale, minRotSpeed, maxRotSpeed, maxDeviance;
        public int maxEmits;
        public GameTimer emissionTimer;
        Vector2 emissionVel;
        public ParticleEmitter() : base()
        {
            particles=new List<GameObject>();
            emissionTimer = new GameTimer();
            emissionTimer.bMultiTrigger = false;
            emissionVel = new Vector2();
            bHoming=true;
            bAccelerate=false;
            bDieOnFade=true;
            fadeRate=1;
            maxDeviance = -1;
            scaleRate = 0;
            SetEmissionRate(1);
            nEmits=1;
            maxEmits = 1000;
            minAngle=0;
            maxAngle=360;
            minRotSpeed = maxRotSpeed = 0;
            minDistance=1;
            maxDistance=2;
            particleLifeTime=1;
            bRandomVel = false;
            texture = null;
            minScale=1;
            maxScale=1;
        }
        public void SetEmissionRate(float emissionRate)
        {
            if (emissionRate == 0)
                emissionTimer.timeInterval = 0;
            else emissionTimer.timeInterval = 1.0f / emissionRate;
        }
        public static float GetRandom(float min, float max)
        {
            float domain=max-min;
            float random = (float)GameManager.random.NextDouble() * domain + min;
            return random;
        }
        public Vector2 GetRandomPos()
        {
            float angle=GetRandom(minAngle,maxAngle)*(float)Math.PI/180;
            float distance=GetRandom(minDistance,maxDistance);
            Vector2 dir=new Vector2((float)Math.Cos(angle), (float)Math.Sin(angle))*distance;
            dir+=pos;
            return dir;
        }
        public Vector2 GetRandomScale()
        {
            float sc=GetRandom(minScale,maxScale);
            return new Vector2(sc,sc);
        }
        public override void React(GameObject obj, Vector2 cp)
        {
        }
        public void Emit()
        {
            for(int i=0;i<nEmits&&particles.Count < maxEmits;i++)
            {
                particles.Add(CustomizeParticle(EmitParticle()));
            }
        }
        public virtual GameObject EmitParticle()
        {
            GameObject p = new GameObject();
            return p;
        }
        public virtual GameObject CustomizeParticle(GameObject p)
        {
            p.pos = GetRandomPos();
            p.scale = GetRandomScale();
            if(texture!=null)
                p.texture = texture;
            p.color = color;
            p.depth = depth;
            if (bRandomVel)
            {
                p.vel = new Vector2(GetRandom(-1, 1), GetRandom(-1, 1)) * moveSpeed;
                if (attachTarget != null && bHardAttach)
                    p.vel += attachTarget.vel;
            }
            else p.vel = emissionVel;
            p.bBlocks = bBlocks;
            p.bMoves = bMoves;
            p.shape = shape;
            p.bCollides = bCollides;
            p.rotSpeed = GetRandom(minRotSpeed, maxRotSpeed);
            if (particleLifeTime > 0.0f)
            {
                p.bOntimer = true;
                p.lifeTime = particleLifeTime;
            }
            return p;
        }
        public void EmitParticles(float time)
        {
            emissionTimer.Update(time);
            while (emissionTimer.IsTime())
                Emit();
        }
        public override void Update(float time)
        {
            List<GameObject> deadParticles=new List<GameObject>();
            EmitParticles(time);
            foreach(GameObject p in particles)
            {
                if (p.bDead
                    || bDieOnFade && p.color.W <= 0.0f
                    || maxDeviance >= 0 && (pos - p.pos).Length() > maxDeviance)
                {
                    if ((pos - p.pos).Length() > maxDeviance)
                        p.bExplodeOnDeath = false;
                    deadParticles.Add(p);
                }
                else
                {
                    if (bHoming && target != null)
                    {
                        Vector2 dir = target.pos - p.pos;
                        if (dir.Length() > 0.0f)
                            dir.Normalize();
                        if (bAccelerate)
                            p.acc = dir * moveAcc;
                        else p.vel = dir * moveSpeed;
                    }
                    else if (!bRandomVel)
                        p.vel = emissionVel;
                    if (fadeRate != 0)
                        p.color.W -= time / fadeRate;
                    if (scaleRate != 0)
                        p.scale *= (1 + time / scaleRate);
                    p.Update(time);
                }
            }
            foreach (GameObject p in deadParticles)
            {
                p.OnDeath();
                particles.Remove(p);
            }
 	        base.Update(time);
        }
        public override void  Draw(SpriteBatch batch)
        {
 	         foreach(GameObject p in particles)
                 p.Draw(batch);
        }
    }
}
